home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / gen.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  13KB  |  725 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    gen.c
  12.  *
  13.  *    Generate code.
  14.  *    Includes main routine and code generation for unary nodes
  15.  *    and leafs.
  16.  *   Revised: Dec 1988    Joe Montgomery
  17.  *
  18.  *   Revised gen.c to call externfunref to declare all functions XREF
  19.  *
  20.  *     other modules:
  21.  *   Revised main.c to use Amiga File System Naming Conventions
  22.  *    Added ?,C,F switches. ? help
  23.  *                  C force data,bss into Chip memory
  24.  *                  F force data,bss into Fast memory
  25.  *    To be added -o switch to specify assembly output
  26.  *   Revised out.c to use MOTOROLA assembly directives in order
  27.  *    to be compatible with C.Gibbs a68k assembler & blink
  28.  *    Added END statement
  29.  *    Changed .comm label,size to label DC.x 0
  30.  *   Revised d2.c so that externs are declared as XREF -----
  31.  *   Revised g2.c & gen.c to declare all called functions XREF
  32.  *     (will need to change this to declare only external functions)
  33.  *
  34.  *
  35.  *   All changes labeled JMM
  36.  *
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include "param.h"
  41. #include "bstok.h"
  42. #include "tytok.h"
  43. #include "flags.h"
  44. #include "nodes.h"
  45. #include "gen.h"
  46.  
  47. NODEP strsave;
  48. int cctest;
  49. static int reserve;
  50. static int tmpused;
  51.  
  52. extern xflags[];
  53. #define debug xflags['g'-'a']
  54.  
  55. #define FAIL    0
  56. #define OKAY    1
  57.  
  58. #define isimmed(np)     ((np)->g_flags & IMMEDID)
  59. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  60. #define isdreg(np)      ((np)->g_token == REGVAR && (np)->g_rno < AREG)
  61. #define istdreg(np)     ((np)->g_token == REGVAR && (np)->g_rno < DRV_START)
  62.  
  63. int cookflags[] = {
  64.     0,
  65.     NOVAL_OK|CC_OK|IMMA_OK,     /* FORSIDE */
  66.     IMMA_OK,            /* FORPUSH */
  67.     CC_OK,                /* FORCC */
  68.     IMMA_OK,            /* FORIMA */
  69.     0,                /* FORADR */
  70.     IMMA_OK,            /* FORINIT */
  71.     0,                /* IND0 */
  72.     0,                /* RETSTRU */
  73. };
  74.  
  75.  
  76.  
  77. extern NODE *blktab;
  78. extern nmerrors;
  79.  
  80. genx(np, cookie)
  81. register NODEP np;
  82. {
  83.     int rv;
  84.  
  85.     if (np == NULL) return;
  86.     if (nmerrors)
  87.         goto bad;
  88.     if (debug) {
  89.         printf("GEN enter");
  90.         printnode(np);
  91.     }
  92.  
  93.     untype(np);
  94.     if (debug>1) {
  95.         printf("after UNTYPE");
  96.         printnode(np);
  97.     }
  98.  
  99.     tmpused = 0;
  100.     gunk(np);
  101.     if (tmpused && tmpused > blktab->b_tsize)
  102.         blktab->b_tsize = tmpused;
  103.     if (debug > 1) {
  104.         printf("after gunk");
  105.         printnode(np);
  106.     }
  107.     order(np);
  108.  
  109.     reserve = 0;
  110.     rv = eval(np, cookie);
  111.     if (rv == OKAY && debug) {
  112.         printf("GEN exit");
  113.         codeprint(np);
  114.     }
  115.     if (rv == OKAY)
  116.         rv = cookmon(np, cookie);
  117.     else
  118.         error("couldnt eval node");
  119.     freenode(np);
  120.     return rv;
  121. bad:
  122.     freenode(np);
  123.     return FAIL;
  124. }
  125.  
  126. eval(np, cookie)
  127. register NODEP np;
  128. {
  129.     int rv;
  130.  
  131.     np->g_r1 = np->g_r2 = -1;
  132.  
  133.     if (np == NULL) return FAIL;
  134.  
  135.     switch (np->g_type) {
  136.  
  137.     default:
  138.         rv = b_eval(np, cookie);
  139.         /* already did freetmps */
  140.         free1(np, np->n_left);
  141.         free1(np, np->n_right);
  142.         break;
  143.  
  144.     case EV_LEFT:
  145.         rv = u_eval(np, cookie);
  146.         freetmps(np);
  147.         free1(np, np->n_left);
  148.         break;
  149.  
  150.     case EV_NONE:
  151.         rv = l_eval(np);
  152.         break;
  153.     }
  154.     return rv;
  155. }
  156.  
  157. u_eval(np, cookie)
  158. register NODEP np;
  159. {
  160.     int subcook = FORADR;
  161.  
  162.     switch (np->g_token) {
  163.     case STAR:
  164.         subcook = FORIMA;
  165.         break;
  166.     case '!':
  167.         subcook = FORCC;
  168.         break;
  169.     }
  170.  
  171.     if (eval(np->n_left, subcook) == FAIL)
  172.         return FAIL;
  173.     return u_sube(np, cookflags[cookie]);
  174. }
  175.  
  176. u_sube(np, flags)
  177. register NODEP np;
  178. {
  179.     register NODEP lp = np->n_left;
  180.     long offs;
  181.     int i;
  182.  
  183.     switch (np->g_token) {
  184.     case '.':
  185.         if (np->g_fldw)
  186.             return fldget(np, flags);
  187.         offs = np->g_offs;
  188.         inherit(np);
  189.         np->g_offs += offs;
  190.         return OKAY;
  191.     case STAR:
  192.         if (isimmed(lp)) {
  193.             inherit(np);
  194.             np->g_flags &= ~IMMEDID;
  195.         } else if (isareg(lp)) {
  196.             indir(np, lp->g_rno);
  197.         } else {    /* NEED A temp */
  198.             if (lp->g_token == OREG && istemp(lp->g_rno))
  199.                 i = lp->g_rno;
  200.             else
  201.                 i = ralloc(AREG);
  202.             addcode(np, "\tmove.l\t<A,R0\n");
  203.             indir(np, i);
  204.         }
  205.         return OKAY;
  206.     case UNARY '&':
  207.         if (isimmed(lp))
  208.             warn("& ignored");
  209.         else if (lp->g_token == REGVAR)
  210.             return FAIL;
  211.         inherit(np);
  212.         np->g_flags |= IMMEDID;
  213.         if ((flags & IMMA_OK) == 0)
  214.             imm_oreg(np);
  215.         return OKAY;
  216.     case '~':
  217.         utemp(np);
  218.         addcode(np, "\tnot.S\tA\n");
  219.         cc_hack(np);
  220.         return OKAY;
  221.     case UNARY '-':
  222.         utemp(np);
  223.         addcode(np, "\tneg.S\tA\n");
  224.         cc_hack(np);
  225.         return OKAY;
  226.     case TCONV:
  227.         castgen(np);
  228.         return OKAY;
  229.     case PUSHER:    /* must not be on left of assign or asn-op */
  230.         if ((lp->g_token != OREG && lp->g_token != REGVAR) ||
  231.             istemp(lp->g_rno) == 0) {
  232.             inherit(np);
  233.             return OKAY;
  234.         }
  235.         addcode(np, "\tmove.S\t<A,-(sp)\n");
  236.         return OKAY;
  237.     case '(':
  238.         if (np->g_ty == ET_A) {         /* struct returned */
  239.             frc_ral(AREG);
  240.             indir(np, AREG);
  241.         } else {
  242.             frc_ral(0);
  243.             retreg(np, 0);
  244.         }
  245.     /* JMM
  246.       ? added XREF statement.  Note I use this regardless of whether
  247.        the function is defined in the module or not.  This is horrible
  248.        and may cause problems.    I will correct this when I can determine
  249.        whether the function is defined in the current module or is an
  250.        external reference. ?
  251.      */     externfuncref(np); /* see out.c */
  252.  
  253.         addcode(np, "\tjsr\t<A\n");
  254.         return OKAY;
  255.     case DOUBLE '+':
  256.         holdcon(np);
  257.         inherit(np);
  258.         addcode(np, "\tadd.S\t#K,A\n");
  259.         cc_hack(np);
  260.         return OKAY;
  261.     case DOUBLE '-':
  262.         holdcon(np);
  263.         inherit(np);
  264.         addcode(np, "\tsub.S\t#K,A\n");
  265.         cc_hack(np);
  266.         return OKAY;
  267.     case POSTINC:
  268.         if ((flags & NOVAL_OK) == 0) {
  269.             i = ralloc(0);
  270.             retreg(np, i);
  271.             addcode(np, "\tmove.S\t<A,A\n");
  272.         }
  273.         addcode(np, "\tadd.S\t#O,<A\n");
  274.         return OKAY;
  275.     case POSTDEC:
  276.         if ((flags & NOVAL_OK) == 0) {
  277.             i = ralloc(0);
  278.             retreg(np, i);
  279.             addcode(np, "\tmove.S\t<A,A\n");
  280.         }
  281.         addcode(np, "\tsub.S\t#O,<A\n");
  282.         return OKAY;
  283.     case CMPBR:
  284.         i = ralloc(0);
  285.         retreg(np, i);
  286.         addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  287.         cc_hack(np);
  288.         return OKAY;
  289.     case '!':
  290.         if (flags & CC_OK) {
  291.             if (iscc(lp)) {
  292.                 i = cctok(lp);
  293.                 i = (i&1) ? i+1 : i-1;  /* reverse truth */
  294.             } else {
  295.                 i = B_EQ;
  296.                 addcode(np, "<Q");
  297.             }
  298.             np->g_token = i + BR_TOK;
  299.         } else {
  300.             if (istdreg(lp))
  301.                 i = lp->g_rno;
  302.             else
  303.                 i = ralloc(0);
  304.             retreg(np, i);
  305.             if (!iscc(lp))
  306.                 addcode(np, "<Q");
  307.             addcode(np, "\tseq\tA\n\tand.w\t#1,A\n");
  308.         }
  309.         return OKAY;
  310.     default:
  311.         printf("Weird u_eval %s ", np->n_name);
  312.         return FAIL;
  313.     }
  314. }
  315.  
  316. holdcon(np)
  317. NODEP np;
  318. {
  319.     np->g_bsize = np->g_offs;
  320. }
  321.  
  322. retreg(np, rno)
  323. NODEP np;
  324. {
  325.     np->g_token = REGVAR;
  326.     np->g_rno = rno;
  327. }
  328.  
  329. indir(np, rno)
  330. register NODEP np;
  331. {
  332.     np->g_token = OREG;
  333.     np->g_offs = 0;
  334.     np->g_rno = rno;
  335. }
  336.  
  337. inherit(np)
  338. register NODEP np;
  339. {
  340.     NODEP lp = np->n_left;
  341.  
  342.     np->g_token = lp->g_token;
  343.     np->g_offs = lp->g_offs;
  344.     np->g_rno = lp->g_rno;
  345.     np->g_flags |= CHILDNM | (lp->g_flags & IMMEDID);
  346. }
  347.  
  348. extern FILE *output;
  349.  
  350. cookmon(np, cookie)
  351. register NODEP np;
  352. {
  353.  
  354.     if (np == NULL) return FAIL;
  355.  
  356.     switch (cookie) {
  357.     case FORCC:
  358.         if (iscc(np)) {
  359.             outcode(np);
  360.             cctest = cctok(np);
  361.         } else {
  362.             if (np->g_token == ICON && isimmed(np)) {
  363.                 cctest = np->g_offs ? B_YES : B_NO;
  364.                 return OKAY;
  365.             }
  366.             outcode(np);
  367.             outsub("Q", np);
  368.             cctest = B_NE;
  369.         }
  370.         return OKAY;
  371.     case FORINIT:
  372.         if (anycode(np) == 0 && (np->g_flags & IMMEDID)) {
  373.             out_a(np, output);
  374.             return OKAY;
  375.         }
  376.         error("bad INIT expr");
  377.         return FAIL;
  378.     case IND0:
  379.         outcode(np);
  380.         if (np->g_token != REGVAR ||
  381.             np->g_rno != 0)
  382.             if (np->g_token == ICON && np->g_offs == 0 &&
  383.                 isimmed(np))
  384.                 outsub("\tclr.S\td0\n", np);
  385.             else
  386.                 outsub("\tmove.S\tA,d0\n", np);
  387.         return OKAY;
  388.     case RETSTRU:
  389.         outcode(np);
  390.         strret(np);
  391.     }
  392.     outcode(np);
  393.     return OKAY;
  394. }
  395.  
  396. anycode(np)
  397. register NODEP np;
  398. {
  399.     if (np->g_code)
  400.         return 1;
  401.     switch (np->g_type) {
  402.     case EV_NONE:
  403.         return 0;
  404.     case EV_LEFT:
  405.         return anycode(np->n_left);
  406.     case EV_RIGHT:
  407.         return anycode(np->n_right);
  408.     case EV_LR:
  409.     case EV_RL:
  410.         return anycode(np->n_left) || anycode(np->n_right);
  411.     }
  412. }
  413.  
  414. l_eval(np)
  415. register NODEP np;
  416. {
  417.     int l1;
  418.  
  419.     switch (np->g_token) {
  420.     case ID:
  421.         switch (np->g_sc) {
  422.         default:    /* EXTERN or HERE */
  423.             np->g_token = ONAME;
  424.             np->g_offs = 0;
  425.             if (np->n_name[0] != '%')
  426.                 nnmins(np, "_");
  427.             else    /* hack for inline name */
  428.                 strcpy(np->n_name, &np->n_name[1]);
  429.             return OKAY;        /* dont free n_nmx */
  430.         case K_STATIC:
  431.             sprintf(np->n_name, "L%d", (int)np->g_offs);
  432.             np->g_offs = 0;
  433.             np->g_token = ONAME;
  434.             break;
  435.         case K_AUTO:
  436.             np->g_rno = AREG+6;
  437.             np->g_token = OREG;
  438.             break;
  439.         case K_REGISTER:
  440.             np->g_token = REGVAR;
  441.             break;
  442.         }
  443.         if (np->n_nmx) {
  444.             freenode(np->n_nmx);
  445.             np->n_nmx = NULL;
  446.         }
  447.         return OKAY;
  448.     case ICON:
  449.         np->g_flags |= IMMEDID;
  450.         return OKAY;
  451.     case FCON:
  452.         np->g_flags |= IMMEDID;
  453.         return OKAY;
  454.     case SCON:
  455.         np->g_flags |= IMMEDID;
  456.         np->g_token = ONAME;
  457.         l1 = new_lbl();
  458.         save_scon(np, l1);
  459.         sprintf(np->n_name, "L%d", l1);
  460.         return OKAY;
  461.     case OREG:
  462.         return OKAY;
  463.     }
  464.     return FAIL;
  465. }
  466.  
  467. save_scon(np, lbl)
  468. NODEP np;
  469. {
  470.     NODEP tp, copyone();
  471.  
  472.     tp = copyone(np);
  473.     tp->g_offs = lbl;
  474.     if (np->n_nmx) {
  475.         freenode(np->n_nmx);
  476.         np->n_nmx = NULL;
  477.     }
  478.     putlist(&strsave, tp);
  479. }
  480.  
  481. utemp(np)
  482. NODEP np;
  483. {
  484.     NODEP lp = np->n_left;
  485.     int i;
  486.  
  487.     if (lp->g_token == REGVAR &&
  488.         istemp(lp->g_rno)) {
  489.         inherit(np);
  490.         return;
  491.     }
  492.     i = ralloc(0);
  493.     retreg(np, i);
  494.     addcode(np, "\tmove.S\t<A,A\n");
  495. }
  496.  
  497. freetmps(np)
  498. register NODEP np;
  499. {
  500.     if (np->g_r1 != -1)
  501.         rfree(np->g_r1);
  502.     if (np->g_r2 != -1)
  503.         rfree(np->g_r2);
  504. }
  505.  
  506. free1(np, cp)
  507. NODEP np, cp;
  508. {
  509.     int cr;
  510.  
  511.     if (cp->g_token != OREG && cp->g_token != REGVAR)
  512.         return;
  513.     cr = cp->g_rno;
  514.     if (np && cr == np->g_rno &&
  515.         (np->g_token == OREG || np->g_token == REGVAR))
  516.         return;
  517.     if (istemp(cr))
  518.         rfree(cr);
  519. }
  520.  
  521. istemp(rno)
  522. {
  523.     return (rno < DRV_START ||
  524.         (rno >= AREG && rno < ARV_START));
  525. }
  526.  
  527. rfree(rno)
  528. {
  529.     reserve &= ~(1<<rno);
  530. }
  531.  
  532. frc_ral(rno)
  533. {
  534.     int i;
  535.  
  536.     i = (1<<rno);
  537.     if (reserve & i)
  538.         error("rno reserved! ");
  539.     reserve |= i;
  540. }
  541.  
  542. tempr(np, type)
  543. NODEP np;
  544. {
  545.     int i;
  546.  
  547.     i = ralloc(type);
  548.     if (np->g_r1 == -1)
  549.         np->g_r1 = i;
  550.     else
  551.         np->g_r2 = i;
  552.     return i;
  553. }
  554.  
  555. ralloc(type)
  556. {
  557.     int starti, endi;
  558.     register int i;
  559.  
  560.     if (type == AREG) {
  561.         starti = AREG;
  562.         endi = ARV_START;
  563.     } else {
  564.         starti = 0;
  565.         endi = DRV_START;
  566.     }
  567.     for (i=starti; i<endi; i++)
  568.         if ((reserve & (1<<i)) == 0) {
  569.             reserve |= (1<<i);
  570.             return i;
  571.         }
  572.     error("Compiler failure - rallo");
  573.     return -1;
  574. }
  575.  
  576.  
  577. extern NODE *blktab;
  578. tmp_alloc(sz)
  579. {
  580.  
  581.     tmpused += sz;
  582.     return blktab->b_size + tmpused;
  583. }
  584.  
  585. /* fixes nodes with no code or aX is temp that are #d(aX) */
  586. imm_oreg(np)
  587. NODEP np;
  588. {
  589.     char *regnm(), buf[30];
  590.     int i;
  591.  
  592.     if (np->g_token != OREG)
  593.         return;
  594.     if ((np->g_flags & IMMEDID) == 0)
  595.         return;
  596.     np->g_flags &= ~IMMEDID;
  597.     if (np->g_offs == 0) {          /* #(a0) -> a0 */
  598.         np->g_token = REGVAR;
  599.         return;
  600.     }
  601.     if (istemp(np->g_rno)) {
  602.         holdcon(np);
  603.         addcode(np, "\tadd\t#K,A\n");
  604.         np->g_token = REGVAR;
  605.         return;
  606.     }
  607.     sprintf(buf, "\tlea\t%d(%s),A\n", (int)np->g_offs, regnm(np->g_rno));
  608.     addcode(np, buf);
  609.     i = ralloc(AREG);
  610.     retreg(np, i);
  611. }
  612.  
  613. castgen(tp)
  614. register NODEP tp;
  615. {
  616.     register NODEP np = tp->n_left;
  617.     int sz = tp->g_sz;
  618.     int i;
  619.  
  620.     if (np->g_token == ICON && isimmed(np)) {
  621.         if (tp->g_ty == ET_F) {
  622.             tp->g_token = FCON;
  623.             *(float *)&tp->g_offs = (float)np->g_offs;
  624.             tp->g_flags |= IMMEDID;
  625.         } else {
  626.             inherit(tp);
  627.             i_exp(tp, np->g_sz, np->g_ty);
  628.             squish(tp);
  629.         }
  630.     } else if (np->g_token == FCON && isimmed(np)) {
  631.         if (tp->g_ty != ET_F) {
  632.             tp->g_token = ICON;
  633.             tp->g_offs = (long)*(float *)&np->g_offs;
  634.             tp->g_flags |= IMMEDID;
  635.             squish(tp);
  636.         } else {
  637.             inherit(tp);
  638.         }
  639.     } else if (sz > np->g_sz) {
  640.         if (np->g_ty == ET_U) {
  641.             i = ralloc(0);
  642.             retreg(tp, i);
  643.             addcode(tp, "\tclr.S\tA\n\tmove.<S\t<A,A\n");
  644.         } else {
  645.             if (isdreg(np)) {
  646.                 inherit(tp);
  647.             } else {
  648.                 i = ralloc(0);
  649.                 retreg(tp, i);
  650.                 addcode(tp, "\tmove.<S\t<A,A\n");
  651.             }
  652.             if (sz == 4 && np->g_sz == 1)
  653.                 addcode(tp, "\text.w\tA\n\text.l\tA\n");
  654.             else
  655.                 addcode(tp, "\text.S\tA\n");
  656.         }
  657.         return;
  658.     }
  659.     else if (sz < np->g_sz) {
  660.         switch (np->g_token) {
  661.         case ONAME:
  662.         case OREG:
  663.             if (isimmed(np)) {
  664. smfudge:
  665.                 i = ralloc(0);
  666.                 retreg(tp, i);
  667.                 addcode(tp, "\tmove.<S\t<A,A\n");
  668.                 return;
  669.             }
  670.             inherit(tp);
  671.             tp->g_offs = np->g_offs + (np->g_sz - sz);
  672.             break;
  673.         case REGVAR:
  674.             if (sz == 1 && np->g_rno >= AREG)
  675.                 goto smfudge;
  676.             /* fall through */
  677.         default:
  678.             inherit(tp);
  679.         }
  680.     } else
  681.         inherit(tp);
  682. }
  683.  
  684. squish(np)
  685. NODEP np;
  686. {
  687.     int neg;
  688.  
  689.     neg = (np->g_ty == ET_S && np->g_offs < 0);
  690.  
  691.     switch (np->g_sz) {
  692.     case 1:
  693.         if (neg)
  694.             np->g_offs |= 0xffffff00L;
  695.         else
  696.             np->g_offs &= 0xff;
  697.         break;
  698.     case 2:
  699.         if (neg)
  700.             np->g_offs |= 0xffff0000L;
  701.         else
  702.             np->g_offs &= 0xffffL;
  703.         break;
  704.     }
  705. }
  706.  
  707. i_exp(np, osz, oty)
  708. NODEP np;
  709. {
  710.     long l;
  711.  
  712.     if (oty == ET_S && osz < np->g_sz) {
  713.         l = np->g_offs;
  714.         switch (osz) {
  715.         case 1:
  716.             l = (char) l;
  717.             break;
  718.         case 2:
  719.             l = (short) l;
  720.             break;
  721.         }
  722.         np->g_offs = l;
  723.     }
  724. }
  725.